package com.gagakuai.bpm.common.aspect;

import com.alibaba.fastjson.JSON;

import com.gagakuai.bpm.common.constants.DistrubutexConstants;
import com.gagakuai.bpm.common.constants.RabbitMqConstants;
import com.gagakuai.bpm.dao.mapper.camunda.ActHiActinstMapper;
import com.gagakuai.bpm.domian.entity.BpmDeadMessageLog;
import com.gagakuai.bpm.domian.entity.camuda.BrokerMessageLog;
import com.gagakuai.bpm.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.Map;

/*
 * @program: mss_server
 * @description: bpm使用mq发送消息
 * @author: houhong
 * @create: 2022-03-24 15:53
 */
@Slf4j
@Component
public class MqBpmSender implements RabbitTemplate.ConfirmCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisUtil redisUtils;

    @Autowired
    private ActHiActinstMapper actHiActinstMapper;


    @PostConstruct
    public void init() {

        rabbitTemplate.setConfirmCallback(this);

    }


    /*
     * @param ack             生产者向rabbit进行消息确认
     * @param cause           原因
     * @param correlationData borker回送消息相关信息
     * @return
     * @Author houhong
     * @Description //TODO
     * @Date 3:55 下午 2022/3/24
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {

        log.info("##correlationData: {}##", JSON.toJSONString(correlationData));

        //保证业务不能重复消费
        String messageId = correlationData.getId();
        String key = DistrubutexConstants.MSG_INFO_BPM_PREX_MSS + messageId;

        Map<Object, Object> hmget = redisUtils.hmget(key);
        if (ack) {

            hmget.put("status", DistrubutexConstants.BPM_WITH_DEAW_SEND_SUCCESS);
        } else {

            hmget.put("status", DistrubutexConstants.BPM_WITH_DEAW_SEND_FAILURE);
            //失败则进行具体的后续操作:重试 或者补偿等手段
            log.info("#【生产者消息】发送失败#");

        }
        hmget.put("updateTime", new Date());
        redisUtils.hmset(key, hmget);

    }


    /*
     * 发布业务系统回调消息
     */
    public void sendSystemCallBackMessage(BpmDeadMessageLog bpmDeadMessageLog) {

        // 使用当前时间当做bpm撤销时间
        Date bpmWithDrawTime = new Date();
        // 插入消息记录表数据
        BrokerMessageLog brokerMessageLog = new BrokerMessageLog();

        String bpmMsgId = bpmDeadMessageLog.getBpmMsgId();

        // 消息唯一ID
        brokerMessageLog.setMessageId(bpmMsgId);
        // 保存消息整体 转为JSON 格式存储入库

        // 设置消息状态为0 表示发送中
        brokerMessageLog.setStatus(DistrubutexConstants.BPM_WITH_DEAW_SENDING);
        // 设置消息未确认超时时间窗口为 一分钟
        brokerMessageLog.setNextRetry(DateUtils.addMinutes(bpmWithDrawTime, DistrubutexConstants.BPM_WITH_DEAW_TIMEOUT));
        brokerMessageLog.setCreateTime(new Date());
        brokerMessageLog.setUpdateTime(new Date());
        //开始射者为0
        brokerMessageLog.setComsumerRetryCount(0);

        // TODO: 2022/3/29 存redis
        Map<Object, Object> map = null;
        try {
            map = org.apache.commons.beanutils.BeanUtils.describe(brokerMessageLog);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String key = DistrubutexConstants.MSG_INFO_BPM_PREX_MSS + bpmMsgId;
        redisUtils.hmset(key, map);

        //消息唯一ID
        CorrelationData correlationData = new CorrelationData(bpmMsgId);

        rabbitTemplate.convertAndSend(RabbitMqConstants.BPM_TOPIC_EXCHANGE, RabbitMqConstants.BPM_EXCEPTION_CALLBACK_ROUTKING_KEY,
                bpmDeadMessageLog, correlationData);
    }


}